package com.cosyhut.blocks.display;

import com.jme.light.PointLight;
import com.jme.math.Vector3f;
import com.jme.renderer.*;
import com.jme.util.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jme.system.*;
import com.jme.scene.*;
import com.jme.scene.state.*;

import com.cosyhut.blocks.engine.*;

/**
 * 
 * @author TimWorks
 * Jan 25, 2007
 * 
 * handling renderer related staff
 *
 */
public class GRenderer {
    private Renderer _renderer;
    private DisplaySystem _window;
    protected Camera _cam;
    protected Node _root;

    public GRenderer(DisplaySystem d) {
        this._window = d;
        this._renderer = this._window.getRenderer();
        this._root = new Node();
        init();
    }
    
    private void init() {
        // -- create camera
        try {
            this._cam = this._renderer.createCamera(this._window.getWidth(),
                    this._window.getHeight());

        } catch (JmeException e) {
            /**
             * If the displaysystem can't be initialized correctly, exit
             * instantly.
             */
            e.printStackTrace();
            System.exit(1);
        }
        /** Set up how our camera sees. */
        cameraPerspective();
        Vector3f loc = new Vector3f(0f, 1.5f, 0.5f);
        Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
        Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
        Vector3f dir = new Vector3f(0.0f, 0f, -1.0f);
        /** Move our camera to a correct place and orientation. */
        this._cam.setFrame(loc, left, up, dir);
        /** Signal that we've changed our camera's location/frustum. */
        this._cam.update();
        
        this._cam.lookAt(new Vector3f(), new Vector3f(0f, 1f, 0f));
        /** Assign the camera to this renderer. */
        this._renderer.setCamera(this._cam);

        // ---- LIGHTS
        /** Set up a basic, default light. */
        PointLight light = new PointLight();
        light.setDiffuse(new ColorRGBA(0.75f, 0.75f, 0.75f, 0.75f));
        light.setAmbient(new ColorRGBA(0.8f, 0.8f, 0.7f, 1.0f));
        light.setLocation(new Vector3f(20, 50, 30));
        light.setEnabled(true);

        LightState lightState;
        /** Attach the light to a lightState and the lightState to rootNode. */
        lightState = this._renderer.createLightState();
        lightState.setEnabled(true);
        lightState.attach(light);
        this._root.setRenderState(lightState);

        // -- update renderer states
//        this._root.updateRenderState();
        
        /** Set a black background. */
        this._renderer.setBackgroundColor(ColorRGBA.black);
        //this._renderer.enableStatistics(true);
    }
    
    protected void cameraPerspective() {
        this._cam.setFrustumPerspective(45.0f, (float) this._window.getWidth()
                / (float) this._window.getHeight(), 1, 1000);
        this._cam.setParallelProjection(false);
        this._cam.update();
    }
    
    public void update() {
        /** Reset display's tracking information for number of triangles/vertexes */
        this._renderer.clearStatistics();
        /** Clears the previously rendered information. */
        this._renderer.clearBuffers();
        
        // Execute renderQueue item
        GameTaskQueueManager.getManager().getQueue(GameTaskQueue.RENDER).execute();
        
        //!! update the node's state everytime it is updated !!
        this._root.updateGeometricState( 0.0f, true );
        
        /** Draw the rootNode and all its children. */
        this._renderer.draw(this._root);

        // swap buffers
        this._renderer.displayBackBuffer();
    }

    public Camera getCamera() {
        return this._cam;
    }
  
    public void addRobot(BRobot r) {
        this._root.attachChild(r.getRoot());
        this._root.updateRenderState();
    }

    public Node getRoot() {
    	return this._root;
    }
    
    // -------------------------------------------------------------------------
    public Renderer getRenderer() {
        return this._renderer;
    }
    
    public void enableDebug(Node root) {
        AlphaState alpha = this._renderer.createAlphaState();
        alpha.setReference(0.5f);
        root.setRenderState(alpha);
        
        ZBufferState zbuffer = this._renderer.createZBufferState();
        root.setRenderState(zbuffer);

        //MaterialState material = this._renderer.createMaterialState();
        //material.setEnabled(true);
        //material.setColorMaterial(MaterialState.defaultColorMaterial);
        //root.setRenderState(material);
        
        WireframeState wireframe = this._renderer.createWireframeState();
        this._root.setRenderState(wireframe);
        
        CullState cull = this._renderer.createCullState();
        CullState.setFlippedCulling(true);
        cull.setCullMode(CullState.CS_NONE);
        root.setRenderState(cull);

        ShadeState shade = this._renderer.createShadeState();
        shade.setShade(ShadeState.SM_FLAT);
        this._root.setRenderState(shade);   
        
        //root.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
        root.updateRenderState();
    }
}
